package com.springboot.aspect;///****************************************************
// * 创建人：  tanglei
// * 创建时间: 2021/12/15/14:40
// * 项目名称：dfbp-biz-offlineipo
// * 文件名称: PreventDuplicationAspect.java
// * 文件描述: @Description:
// *
// * All rights Reserved, Designed By 投资交易团队
// * @Copyright:2016-2021
// *
// ********************************************************/
//package src.aspect;
//
//import cn.hutool.core.date.DateUtil;
//import cn.hutool.core.lang.Assert;
//import cn.hutool.core.util.StrUtil;
//import com.alibaba.fastjson.JSONObject;
//import com.win.dfas.common.annotation.NoRepeatSubmit;
//import com.win.dfas.common.exception.WinException;
//import com.win.dfas.common.util.RequestUtil;
//import lombok.extern.slf4j.Slf4j;
//import org.aspectj.lang.ProceedingJoinPoint;
//import org.aspectj.lang.annotation.Around;
//import org.aspectj.lang.annotation.Aspect;
//import org.aspectj.lang.annotation.Pointcut;
//import org.aspectj.lang.reflect.MethodSignature;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.data.redis.core.script.DigestUtils;
//import org.springframework.stereotype.Component;
//import org.springframework.web.context.request.RequestContextHolder;
//import org.springframework.web.context.request.ServletRequestAttributes;
//
//import javax.servlet.http.HttpServletRequest;
//import java.lang.reflect.Method;
//import java.util.Objects;
//import java.util.concurrent.TimeUnit;
//
///**
// * 包名称：  com.win.dfbp.biz.offlineipo.common.aspect
// * 接口名称：PreventDuplicationAspect
// * 接口描述：
// * 创建人：  tanglei
// * 创建时间：2021/12/15 14:40
// */
//@Slf4j
//@Aspect
//@Component
//public class PreventRepeatSubmitAspect {
//
//    @Autowired
//    private RedisTemplate redisTemplate;
//
//    public static final String PREVENT_REAPEAT_SUBMIT = "PREVENT_REAPEAT_SUBMIT_";
//
//    /**
//     * 定义切点
//     */
//    @Pointcut("@annotation(com.win.dfas.common.annotation.NoRepeatSubmit)")
//    public void preventRepeatSubmit() {
//    }
//
//    /**
//     * 环绕通知 （可以控制目标方法前中后期执行操作，目标方法执行前后分别执行一些代码）
//     *
//     * @param joinPoint
//     * @return
//     */
//    @Around("preventRepeatSubmit()")
//    public Object before(ProceedingJoinPoint joinPoint) throws Exception {
//        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
//                .getRequestAttributes();
//        HttpServletRequest request = attributes.getRequest();
//        Assert.notNull(request, "request cannot be null.");
//        String url = request.getRequestURI();
//        //获取执行方法
//        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
//        //获取防重复提交注解
//        NoRepeatSubmit annotation = method.getAnnotation(NoRepeatSubmit.class);
//        // 获取用户code以及方法标记，生成redisKey和redisValue
//        String userCode = RequestUtil.getUserCode();
//        log.debug("current user is {}...", userCode);
//        //redis 标记key
//        String redisKey = PREVENT_REAPEAT_SUBMIT
//                .concat(userCode).concat(StrUtil.UNDERLINE)
//                .concat(getMethodSign(method, joinPoint.getArgs()));
//
//        //redis value
//        String redisValue = url.concat(StrUtil.UNDERLINE).concat(DateUtil.now());
//
//        log.debug("prevent repeat submit redis key is {}, value is {}", redisKey, redisValue);
//
//        if (redisTemplate.hasKey(redisKey)) {
//            throw new WinException(annotation.message());
//        } else {
//            //设置防重复操作限时标记（前置通知）
//            redisTemplate.opsForValue()
//                    .set(redisKey, redisValue, annotation.interval(), TimeUnit.MILLISECONDS);
//            try {
//                //正常执行方法并返回
//                //ProceedingJoinPoint类型参数可以决定是否执行目标方法，且环绕通知必须要有返回值，返回值即为目标方法的返回值
//                return joinPoint.proceed();
//            } catch (Throwable throwable) {
//                log.error("防重复操作环绕返回异常，{}", throwable);
//                //异常释放标记
//                redisTemplate.delete(redisKey);
//                throw new RuntimeException(throwable);
//            }
//        }
//    }
//
//    /**
//     * @description:  对方法、参数 采用算法SHA1加密 格式化为字符串
//     * @param method
//     * @param args
//     * @return: java.lang.String
//     * @author: tanglei
//     * @time: 2021/12/15 16:07
//     */
//    private String getMethodSign(Method method, Object... args) {
//        StringBuilder sb = new StringBuilder(method.toString());
//        for (Object arg : args) {
//            sb.append(toString(arg));
//        }
//        return DigestUtils.sha1DigestAsHex(sb.toString());
//    }
//
//    /**
//     * @description:  格式化为字符串
//     * @param arg
//     * @return: java.lang.String
//     * @author: tanglei
//     * @time: 2021/12/15 15:02
//     */
//    private String toString(Object arg) {
//        if (Objects.isNull(arg)) {
//            return "null";
//        }
//        if (arg instanceof Number) {
//            return arg.toString();
//        }
//        return JSONObject.toJSONString(arg);
//    }
//}
//
